import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import * as THREE from 'three'
import gsap from 'gsap'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
import eventBus from '@/utils/eventBus'
import cameraModule from '../camera'
import controlModule from '../controls'
import { CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer'
import vertexShader from '@/shader/fighter/vertex.glsl'
import fragmentShader from '@/shader/fighter/fragment.glsl'
export default class City {
    constructor(scene) {
        this.scene = scene
        this.floor1Group
        this.floor2Group
        this.wallGroup
        this.floor2Tags = []

        this.loader = new GLTFLoader()
        const dracoLoader = new DRACOLoader()
        dracoLoader.setDecoderPath('./draco/')
        this.loader.setDRACOLoader(dracoLoader)

        this.loader.load('./model/floor2.glb', gltf => {
            scene.add(gltf.scene)
            this.floor2Group = gltf.scene

            let array = ["小型会议室", "核心科技室", "科技展台", "设计总监办公室"];

            gltf.scene.traverse(child => {
                if(child.isMesh) {
                    child.material.emissiveIntensity = 0.1; // 放射光强度。调节发光颜色。默认为1
                }

                // 展台添加标注（利用场景预设的空物体，获取他的位置，填充标注元素）
                if(array.indexOf(child.name) != -1) {
                    const css3dObject = this.createTag(child)
                    css3dObject.visible = false
                    this.floor2Tags.push(css3dObject)
                    this.floor2Group.add(css3dObject)
                }
            });
            this.floor2Group.visible = false
        });

        this.loader.load('./model/floor1.glb', gltf => {
            this.floor1Group = gltf.scene
            // 判断子元素是否是物体
            gltf.scene.traverse(child => {
                if(child.isMesh) {
                    child.material.emissiveIntensity = 5
                }
            });
            this.floor1Group.visible = false
            scene.add(gltf.scene)
        });

        this.loader.load('./model/wall.glb', gltf => {
            scene.add(gltf.scene)
            this.wallGroup = gltf.scene
        });

        this.loader.load('./model/Fighter1.glb', gltf => {
            this.fighterGroup = gltf.scene
            scene.add(this.fighterGroup)
            this.fighterGroup.position.set(3, 42, 68)
            this.fighterGroup.traverse(child => {
                if(child.isMesh) {
                    child.material.emissiveIntensity = 15
                    child.position2 = child.position.clone() // 先保存原位置用于恢复飞机
                }
            });
            this.mouse = new THREE.Vector2();
            this.raycaster = new THREE.Raycaster();
            // 事件监听
            window.addEventListener('click', event => {
                event.mesh = this
                // 将鼠标位置归一化为设备坐标，x和y方向的取值范围是 -1~1
                this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
                this.mouse.y = -((event.clientY / window.innerHeight) * 2 - 1)
                // 通过摄像机和鼠标位置更新射线
                this.raycaster.setFromCamera(this.mouse, cameraModule.activeCamera)
                // 进行检测
                const intersects = this.raycaster.intersectObject(this.fighterGroup)
                if(intersects.length > 0) {
                    console.log('点击了战斗机')
                    if(this.floor2Group.visible) {
                        this.floor2Group.visible = false
                        this.floor2Tags.forEach(tag => {
                            tag.visible = false
                        })
                    } else {
                        this.floor2Group.visible = true
                        this.floor2Tags.forEach(tag => {
                            tag.visible = true
                        })
                    }
                }
            });
        })

        this.initEvent()
    }

    update(time) {
    }

    createTag(child) {
        const element = document.createElement('div')
        element.className = 'elementTag'
        element.innerHTML = `
            <div class="elementContent">
                <h3>${child.name}</h3>
                <p>温度：26°</p>
                <p>湿度：50%</p>
            </div>
        `;

        const objectCSS3D = new CSS3DObject(element)
        objectCSS3D.position.copy(child.position)
        objectCSS3D.scale.set(0.2, 0.2, 0.2)
        return objectCSS3D
    }

    showFloor1() {
        this.floor1Group.visible = true
    }
    showFloor2() {
        this.floor2Group.visible = true
        this.floor2Tags.forEach(tag => {
            tag.visible = true
        })
    }
    showWall() {
        this.wallGroup.visible = true
    }
    hideFloor1() {
        this.floor1Group.visible = false
    }
    hideFloor2() {
        this.floor2Group.visible = false
        this.floor2Tags.forEach(tag => {
            tag.visible = false
        })
    }
    hideWall() {
        this.wallGroup.visible = false
    }

    initEvent() {
        eventBus.on('showFloor1', () => {
            this.showFloor1()
            this.hideFloor2()
            this.hideWall()
        });
        eventBus.on('showFloor2', () => {
            this.showFloor2()
            this.hideFloor1()
            this.hideWall()
        });
        eventBus.on('showWall', () => {
            this.showWall()
            this.hideFloor1()
            this.hideFloor2()
        });
        eventBus.on('showAll', () => {
            this.showFloor1()
            this.showFloor2()
            this.showWall()

            gsap.to(this.wallGroup.position, {
                y: 200,
                duration: 1
            });

            gsap.to(this.floor2Group.position, {
                y: 50,
                duration: 1,
                delay: 1
            })
        });
        eventBus.on('hideAll', () => {
            gsap.to(this.floor2Group.position, {
                y: 0,
                duration: 1
            });

            gsap.to(this.wallGroup.position, {
                y: 0,
                duration: 1,
                delay: 1,
                onComplete: () => {
                    this.hideFloor1()
                    this.hideFloor2()
                }
            })
        });

        eventBus.on('flatFighter', () => {
            // 将飞机展成立方体
            // 获取立方体点的位置
            const positions = []
            for(let i = 0; i < 5; i++) {
                for(let j = 0; j < 5; j++) {
                    positions.push(new THREE.Vector3(i*2-2, j*2-2, 0))
                }
            }

            let n = 0;
            this.fighterGroup.traverse(child => {
                if(child.isMesh) {
                    positions[n].multiplyScalar(10) // 将点位放大10倍

                    gsap.to(child.position, {
                        x: "+=" + positions[n].x,
                        y: "+=" + positions[n].y,
                        z: "+=" + positions[n].z,
                        duration: 1
                    });
                    n++;
                }
            })
        });

        eventBus.on('recoverFighter', () => {
            this.fighterGroup.traverse(child => {
                if(child.isMesh) {
                    gsap.to(child.position, {
                        x: child.position2.x,
                        y: child.position2.y,
                        z: child.position2.z,
                        duration: 1
                    })
                }
            })
        });

        eventBus.on('pointsFighter', () => {
            this.createPoints(this.fighterGroup)
        });

        eventBus.on('pointsBlast', () => {
            this.pointsBlast()
        });

        eventBus.on('pointsBack', () => {
            this.pointsBack()
        })
    }

    showFighter() {
        this.floor1Group && (this.floor1Group.visible = false)
        this.floor2Group && (this.floor2Group.visible = false)
        this.wallGroup && (this.wallGroup.visible = false)
        this.fighterGroup.visible = true
    }

    createPoints(object3d) {
        if(!this.fighterPointsGroup) {
            this.fighterPointsGroup = this.transformPoints(object3d)
            this.scene.add(this.fighterPointsGroup)
        }
    }

    transformPoints(object3d) {
        // 创建纹理贴图
        const texture = new THREE.TextureLoader().load('./particles/1.png');
        const group = new THREE.Group()

        // 注意层级，所以递归子元素
        function createPoints(object3d, newObject3d) {
            if(object3d.children.length > 0) {
                object3d.children.forEach(child => {
                    if(child.isMesh) {
                        // 随机生成颜色
                        const color = new THREE.Color(
                            Math.random(),
                            Math.random(),
                            Math.random()
                        );

                        /* const material = new THREE.PointsMaterial({
                            size: 0.1,
                            color,
                            map: texture,
                            blending: THREE.AdditiveBlending, // 叠加亮度，点越多越亮
                            transparent: true,
                            depthTest: false
                        }); */

                        const material = new THREE.ShaderMaterial({
                            uniforms: {
                                uColor: { value: color },
                                uTexture: { value: texture },
                                uTime: { value: 0 }
                            },
                            vertexShader,
                            fragmentShader,
                            blending: THREE.AdditiveBlending,
                            transparent: true,
                            depthTest: false
                        });

                        const points = new THREE.Points(child.geometry, material);
                        points.position.copy(child.position);
                        points.rotation.copy(child.rotation);
                        points.scale.copy(child.scale);

                        newObject3d.add(points)
                        createPoints(child, points)
                    }
                });
            }
        }

        createPoints(object3d, group);
        return group;
    }

    pointsBlast() {
        this.fighterPointsGroup.traverse(child => {
            // 对点元素进行散开
            if(child.isPoints) {
                // 开辟数组空间
                let randomPostionArray = new Float32Array(
                    child.geometry.attributes.position.count * 3
                );
                for(let i = 0; i < child.geometry.attributes.position.count; i++) {
                    // 范围是-10 ~ 10
                    randomPostionArray[i * 3 + 0] = (Math.random() * - 1) * 10;
                    randomPostionArray[i * 3 + 1] = (Math.random() * - 1) * 10;
                    randomPostionArray[i * 3 + 2] = (Math.random() * - 1) * 10;
                }
                // 3个点为一组，决定每个顶点要散开到的位置
                const aPosition = new THREE.BufferAttribute(randomPostionArray, 3);
                child.geometry.setAttribute('aPosition', aPosition);

                gsap.to(child.material.uniforms.uTime, {
                    value: 10,
                    duration: 5
                })
            }
        })
    }

    pointsBack() {
        this.fighterPointsGroup.traverse(child => {
            if(child.isPoints) {
                gsap.to(child.material.uniforms.uTime, {
                    value: 0,
                    duration: 5
                })
            }
        })
    }
}